package jp.sourceforge.akjrcp.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//TODO:update akj betas.
public class ProcessMonitor {
	Log log=LogFactory.getLog(ProcessMonitor.class);
	Process process;
	boolean monitor;
	ProcessPrinter printer;
	private boolean monitorInput=true;
	private boolean monitorError=true;
	
	private boolean inputClosed;
	private boolean errorClosed;
	public boolean isErrorClosed() {
		return errorClosed;
	}
	public boolean isInputClosed() {
		return inputClosed;
	}
	public ProcessMonitor(Process process,ProcessPrinter printer){
		this.process=process;
		this.printer=printer;
	}
	public void startMonitor(){
		monitor=true;
		if(monitorError){
			new ErrorMonitor().start();
		}else{
			errorClosed=true;
		}
		if(monitorInput){
			new InputMonitor().start();
		}else{
			//already finished
			inputClosed=true;
		}
	}
	InputStream inputStream,errorStream;
	public class ErrorMonitor extends Thread{
		public void run(){
			log.info("errorMonitor:start");
			
			if(printer==null){

				errorStream=process.getErrorStream();
				
					try {
						while(errorStream.read()!=-1){
							
						}
					} catch (IOException e) {
						
						e.printStackTrace();
					}finally{
						try {
							errorStream.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
						
					}
			}else{
			errorStream=process.getErrorStream();
			
			
			BufferedReader breader=new BufferedReader(new InputStreamReader(errorStream));
			
			int b;
			StringBuffer buffer=new StringBuffer();
			try {
				while((b=breader.read())!=-1){//some time error happn,if it finished so quickly
					if((char)b=='\n'){
					//	log.infon");
					printer.printError(buffer.toString()+"\n");
					
					buffer=new StringBuffer();
					}else if((char)b=='\r'){
						printer.printError(buffer.toString()+"\n");
						buffer=new StringBuffer();
						//log.infor");
					}else{
						buffer.append((char)b);
					}
					
				}
				breader.close();
				errorStream.close();
				
				errorClosed=true;
				log.info("error close");
				if(buffer.length()>0){
					printer.printError(buffer.toString()+"\n");
				}
			} catch (IOException e) {
				
					try {
						errorStream.close();
						inputStream.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				
				e.printStackTrace();
			}
			
			}
			
			/*
			//this aproach sometime 
			InputStreamReader inputRead=new InputStreamReader(process.getErrorStream());
			BufferedReader breader=new BufferedReader(inputRead);
			for(int i=0;i<300;){
				try {
					if(breader.ready()){
						break;
					}else{
						try {
							log.info("wait-buffer:"+i);
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			String line;
			try {
				while((line=breader.readLine())!=null){
					printer.printError(line+"\n");
				}
				breader.close();
				
				//errorReader.close();
				errorClosed=true;
				log.info("error close");
			} catch (IOException e) {
				try {
					//errorReader.close();
					inputReader.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}*/
			/*
			errorReader=process.getErrorStream();
			int b;
			StringBuffer buffer=new StringBuffer(512);
			try {
				while((b=errorReader.read())!=-1){//some time error happn,if it finished so quickly
					if((char)b=='\n'){
					//	log.infon");
					printer.printError(buffer.toString()+"\n");
					
					buffer=new StringBuffer();
					}else if((char)b=='\r'){
						printer.printError(buffer.toString()+"\n");
						buffer=new StringBuffer();
						//log.infor");
					}else{
						buffer.append((char)b);
					}
					
				}
				errorReader.close();
				errorClosed=true;
				log.info("error close");
				if(buffer.length()>0){
					printer.printError(buffer.toString()+"\n");
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				
					try {
						errorReader.close();
						inputReader.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				
				e.printStackTrace();
			}
		*/	
		}
	}
	
	public class InputMonitor extends Thread{
		public void run(){
			log.info("inputMonitor:start");
			
			
			if(printer==null){
				inputStream=process.getInputStream();
				
					try {
						while(inputStream.read()!=-1){
							
						}
					} catch (IOException e) {
						
						e.printStackTrace();
					}finally{
						try {
							inputStream.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
						
					}
			}
			else{
				inputStream=process.getInputStream();
			int b;
			StringBuffer buffer=new StringBuffer();
			try {
				while((b=inputStream.read())!=-1){
					
					if((char)b=='\n'){
					printer.printOutput(buffer.toString()+"\n");
					buffer=new StringBuffer();
					}else if((char)b=='\r'){
						printer.printOutput(buffer.toString()+"\n");
						buffer=new StringBuffer();
					}else{
						buffer.append((char)b);
					}
					
				}
				inputStream.close();
				log.info("input close");
				inputClosed=true;
				if(buffer.length()>0){
					printer.printOutput(buffer.toString()+"\n");
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		}
	}
	
	/*
	BufferedReader inputReader,errorReader;
	
	public class ErrorMonitor extends Thread{
		public void run(){
			InputStream input=process.getErrorStream();
			
			inputReader=new BufferedReader(new InputStreamReader(input));
			String line2;
			try {
				while((line2=inputReader.readLine())!=null){
					printer.printError(line2+"\n");
					//Akj_betasPlugin.getDefault().addLog();
				}
				inputReader.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public class InputMonitor extends Thread{
		public void run(){
			InputStream input=process.getInputStream();
			
			errorReader=new BufferedReader(new InputStreamReader(input));
			String line2;
			try {
				while((line2=errorReader.readLine())!=null){
					printer.printOutput(line2+"\n");
				}
				errorReader.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}*/

	public void stop() {
		try {
			inputStream.close();
			errorStream.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public boolean isMonitorInput() {
		return monitorInput;
	}
	public void setMonitorInput(boolean monitorInput) {
		this.monitorInput = monitorInput;
	}
	public boolean isMonitorError() {
		return monitorError;
	}
	public void setMonitorError(boolean monitorError) {
		this.monitorError = monitorError;
	}
}